package utils

import (
	"bytes"
	"crypto/md5"
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"encoding/hex"
	"encoding/pem"
	"os"
	"path/filepath"
	"reflect"
	"runtime"
	"strings"
)

// GetMd5ToLow Md5加密小写
func GetMd5ToLow(str string) string {

	m := md5.New()
	m.Write([]byte(str))
	result := hex.EncodeToString(m.Sum(nil))
	result = strings.ToLower(result)
	return result
}

// InArrary 是否在数组
func InArrary(arr interface{}, ele interface{}) int {
	if reflect.TypeOf(arr).Kind() != reflect.Slice && reflect.TypeOf(arr).Kind() != reflect.Array {
		return -1
	}
	//数组为空
	if reflect.ValueOf(arr).Len() == 0 {
		return 1
	}
	// 数组和元素不一致
	if reflect.ValueOf(arr).Index(0).Type().Kind() != reflect.TypeOf(ele).Kind() {
		return 1
	}
	for i := 0; i < reflect.ValueOf(arr).Len(); i++ {
		if reflect.ValueOf(arr).Index(i).Interface() ==
			reflect.ValueOf(ele).Interface() {
			return 0
		}
	}
	return 1
}

// 将程序变成守护进程。
func Daemonize() {
	if runtime.GOOS == "windows" {
		// windows不支持进程守护,直接return
		return
	}
	if runtime.GOOS == "linux" {
		if os.Getppid() != 1 { //判断当其是否是子进程，当父进程return之后，子进程会被 系统1 号进程接管
			filePath, _ := filepath.Abs(os.Args[0]) //将命令行参数中执行文件路径转换成可用路径
			os.StartProcess(filePath, os.Args[1:], &os.ProcAttr{Files: []*os.File{os.Stdin, os.Stdout, os.Stderr}})
			os.Exit(0)
		} else {
			return
		}
	}
}

/*
 * RSA私钥解密
 */
func RSADecrypt(src []byte, buf []byte) ([]byte, error) {
	block, _ := pem.Decode(buf)
	if block == nil {
		return nil, nil
	}
	// 解析出一个der编码的私钥
	privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)

	// 私钥解密
	result, err := rsa.DecryptPKCS1v15(rand.Reader, privateKey, src)
	if err != nil {
		return nil, err
	}
	return result, nil
}

func RSAEncrypt(src []byte, buf []byte) ([]byte, error) {

	block, _ := pem.Decode(buf)
	if block == nil {
		return nil, nil
	}
	// 解析一个der编码的公钥
	publicKey, err := x509.ParsePKCS1PublicKey(block.Bytes)
	if err != nil {
		return nil, err
	}

	// 公钥加密
	result, _ := rsa.EncryptPKCS1v15(rand.Reader, publicKey, src)
	return result, nil
}

func GenRsaKey(bits int) ([]byte, []byte) {
	pribuf := bytes.NewBuffer([]byte{})
	pubbuf := bytes.NewBuffer([]byte{})
	// 生成私钥文件
	privateKey, err := rsa.GenerateKey(rand.Reader, bits)
	if err != nil {
		return nil, nil
	}
	derPrivateStream := x509.MarshalPKCS1PrivateKey(privateKey)
	block := &pem.Block{
		Type:  "RSA PRIVATE KEY",
		Bytes: derPrivateStream,
	}
	err = pem.Encode(pribuf, block)
	if err != nil {
		return nil, nil
	}
	// 生成公钥文件
	publicKey := &privateKey.PublicKey
	derPkix := x509.MarshalPKCS1PublicKey(publicKey)
	block = &pem.Block{
		Type:  "RSA PUBLIC KEY",
		Bytes: derPkix,
	}

	err = pem.Encode(pubbuf, block)
	if err != nil {
		return nil, nil
	}
	return pubbuf.Bytes(), pribuf.Bytes()
}
